package com.lenovo.nova.util;

import java.util.ArrayList;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.os.IBinder;
import android.view.KeyEvent;
import android.view.MotionEvent;

import com.lenovo.nova.service.IRemoteExecute;
import com.lenovo.nova.util.Constant.Debug;
import com.lenovo.nova.util.debug.CrashHandler;
import com.lenovo.nova.util.debug.MyOldLog;
import com.lenovo.nova.util.debug.mylog;
import com.lenovo.nova.util.debug.slog;

public class Applications extends android.app.Application {
	public static boolean isInDebugMode = true;
	private static Applications instance = null;

	private boolean isInTouchMode = false;

	private ArrayList<OnInputModeChangeListener> mInputModeChangeListeners = new ArrayList<OnInputModeChangeListener>();
	private ArrayList<OnTouchBoardTouchedListener> mTochBoardTouchedListeners = new ArrayList<OnTouchBoardTouchedListener>();
	private ArrayList<OnInputMethodShowOrHideListener> mInputMethodShowOrHideListeners = new ArrayList<OnInputMethodShowOrHideListener>();
	private ArrayList<ConnectedRemoteExecute> mConnectedFinishListeners = new ArrayList<ConnectedRemoteExecute>();
	private ArrayList<OnKeyBackClickListener> mOnKeyBackClickListeners = new ArrayList<OnKeyBackClickListener>();
	private ArrayList<OnMotionEventListener> mMotionEventListeners = new ArrayList<OnMotionEventListener>();
    private ArrayList<OnTouchEventListener> mTouchEventListeners = new ArrayList<OnTouchEventListener>();

	private IRemoteExecute mRemoteExecute;
	private boolean isActivityAlive;
	
	public static Applications get(Context context) {
		if (instance == null) {
			try {
				instance = (Applications) context.getApplicationContext();
			} catch (Exception e) {
				instance = new Applications();
			}
		}
		return instance;
	}

	public static Applications get() {
        if(instance == null){
            instance = new Applications();
        }
		return instance;
	}


	public boolean isDebugMode() {
		return isInDebugMode;
	}

	public boolean isActivityAlive() {
		return isActivityAlive;
	}

	public void setActivityAlive(boolean alive){
		isActivityAlive = alive;
	}
	

	public void setTouchMode(boolean b) {
		isInTouchMode = b;
	}

	public boolean isInTouchMode() {
		return isInTouchMode;
	}


    public void notifyTouchEventChangeListener(MotionEvent ev) {
        for (OnTouchEventListener l : mTouchEventListeners) {
            l.onTouchEvent(ev);
        }
    }

    public void addOnTouchEventChangeListener(OnTouchEventListener l) {
        removeTouchEventChangeListener(l);
        mTouchEventListeners.add(l);
    }

    public void removeTouchEventChangeListener(OnTouchEventListener l) {
        if (mTouchEventListeners != null) {
            if (mTouchEventListeners.contains(l)) {
                mTouchEventListeners.remove(l);
            }
        }
    }

	public void notifyMotionEventChangeListener(MotionEvent ev) {
		for (OnMotionEventListener l : mMotionEventListeners) {
			l.onMotion(ev);
		}
	}

	public void addOnMotionEventListener(OnMotionEventListener l) {
		removeMotionEventListener(l);
		mMotionEventListeners.add(l);
	}

	public void removeMotionEventListener(OnMotionEventListener l) {
		if (mMotionEventListeners != null) {
			if (mMotionEventListeners.contains(l)) {
				mMotionEventListeners.remove(l);
			}
		}
	}

	public void addConnectedExecuteFinishListener(ConnectedRemoteExecute l) {
		mConnectedFinishListeners.add(l);
	}

	public void removeConnectedExecuteFinishListener(ConnectedRemoteExecute l) {
		if (mConnectedFinishListeners != null) {
			if (mConnectedFinishListeners.contains(l)) {
				mConnectedFinishListeners.remove(mConnectedFinishListeners);
			}
		}
	}

	public void notifyInputShowOrHide(boolean show) {
	
	}

	public void addOnInputMethodShowOrHideListener(OnInputMethodShowOrHideListener l) {
		if (mInputMethodShowOrHideListeners != null) {
			if (l != null) {
				removeInputMethodShowOrHideListener(l);
			}

			mInputMethodShowOrHideListeners.add(l);
		}
	}

	public void removeInputMethodShowOrHideListener(OnInputMethodShowOrHideListener l) {
		if (mInputMethodShowOrHideListeners != null) {
			if (mInputMethodShowOrHideListeners.contains(l)) {
				mInputMethodShowOrHideListeners.remove(l);
			}
		}
	}

	public void notifyInputModeChange(boolean inTouchMode) {

        try {
            for (int i = 0; i < mInputModeChangeListeners.size(); i++) {
                mInputModeChangeListeners.get(i).onInputModeChange(inTouchMode);
            }
        } catch (Exception e) {

        }

    }

	public void addOnInputModeChangeListener(OnInputModeChangeListener l) {
		if (mInputModeChangeListeners != null) {
			if (mInputModeChangeListeners.contains(l)) {
				mInputModeChangeListeners.remove(l);
			}
			mInputModeChangeListeners.add(l);
		} else {
			MyOldLog.e("Error mInputModeChangeListeners is null");
		}
	}

	public void removeOnInputChangeListener(OnInputModeChangeListener l) {
		if (mInputModeChangeListeners != null) {
			mInputModeChangeListeners.remove(l);
		} else {
			MyOldLog.e("Error mInputModeChangeListeners is null");
		}
	}

	public void addOnKeyBackClickListener(OnKeyBackClickListener l) {
		if (l != null) {
			removeOnKeyBackClickListener(l);
			mOnKeyBackClickListeners.add(l);
		}
	}

	public void removeOnKeyBackClickListener(OnKeyBackClickListener l) {
		if (l != null) {
			mOnKeyBackClickListeners.remove(l);
		}
	}

	public void notifyTouchBoardTouched(KeyEvent event) {
		slog.p("notifyTouchBoardTouched action " + event.getAction() + " size " + mTochBoardTouchedListeners);
		if (mTochBoardTouchedListeners != null) {
			for (OnTouchBoardTouchedListener l : mTochBoardTouchedListeners) {
				l.onTouchBoardTouched(event);
			}
		}
	}

	public void addOnTochBoardTouchedListener(OnTouchBoardTouchedListener l) {
		if (mTochBoardTouchedListeners != null) {
			if (mTochBoardTouchedListeners.contains(l)) {
				mTochBoardTouchedListeners.remove(l);
			}
			mTochBoardTouchedListeners.add(l);
		} else {
			MyOldLog.e("Error mTochBoardTouchedListeners is null");
		}
	}

	public void removeOnTouchBoardListener(OnTouchBoardTouchedListener l) {
		if (mTochBoardTouchedListeners != null) {
			mTochBoardTouchedListeners.remove(l);
		} else {
			MyOldLog.e("Error mTochBoardTouchedListeners is null");
		}
	}

	public void getRemoteExecuteAndAddConnectionCallBack(ConnectedRemoteExecute conn) {
		bindRemoteExecuteService(conn);
	}

	public void bindRemoteExecuteService() {
		bindRemoteExecuteService(null);
	}

	public void bindRemoteExecuteService(ConnectedRemoteExecute conn) {
		if (mRemoteExecute == null) {
			Intent intent = new Intent("com.lenovo.nova.app.service");
			if (conn != null) {
				addConnectedExecuteFinishListener(conn);
			}
			bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
			MyOldLog.p("it is bindService ..... ");
		} else {
			if (conn != null) {
				conn.onConnectedFinish(mRemoteExecute);
			}
			MyOldLog.p("bindservice success");
		}
	}

	public void unBindService() {
		unbindService(mConnection);
	}

	public IRemoteExecute getRemoteExecute() {
		// long currentTime = System.currentTimeMillis();
		bindRemoteExecuteService();
		// try {
		// while (mRemoteExecute == null){
		// Thread.sleep(500);
		// long distance = System.currentTimeMillis() - currentTime;
		// // MyLog.e("wait ... bindservice " + distance);
		// if(distance >= 10000){
		// return null;
		// }
		// }
		// } catch (InterruptedException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }
		return mRemoteExecute;
	}

	public void init() {
		isInTouchMode = false;
        SaveValue saveValue = new SaveValue(getApplicationContext());
		String value = saveValue.get(Constant.Debug.KEY_DEBUG_SWITCH);
		isInDebugMode = value == null ? false : value.equals("true");
//        CrashHandler.getInstance().init(getApplicationContext());
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
		mylog.i(Debug.METHOD_TAG, "onCrate");
		// bindRemoteExecuteService();
	}

	@Override
	public void onTerminate() {
		super.onTerminate();
        mylog.i(Debug.METHOD_TAG, "onTerminate");
		unbindService(mConnection);
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
        mylog.i(Debug.METHOD_TAG, "onConfigurationChanged");
	}

	@Override
	public void onLowMemory() {
		super.onLowMemory();
        mylog.i(Debug.METHOD_TAG, "onLowMemory");
	}

	@SuppressLint("NewApi")
	@Override
	public void onTrimMemory(int level) {
		super.onTrimMemory(level);
		// TRIM_MEMORY_COMPLETE：内存不足，并且该进程在后台进程列表最后一个，马上就要被清理
		// TRIM_MEMORY_MODERATE：内存不足，并且该进程在后台进程列表的中部。
		// TRIM_MEMORY_BACKGROUND：内存不足，并且该进程是后台进程。
		// TRIM_MEMORY_UI_HIDDEN：内存不足，并且该进程的UI已经不可见了。
		// 以上4个是4.0增加
		// TRIM_MEMORY_RUNNING_CRITICAL：内存不足(后台进程不足3个)，并且该进程优先级比较高，需要清理内存
		// TRIM_MEMORY_RUNNING_LOW：内存不足(后台进程不足5个)，并且该进程优先级比较高，需要清理内存
		// TRIM_MEMORY_RUNNING_MODERATE：内存不足(后台进程超过5个)，并且该进程优先级比较高，需要清理内存
		mylog.i(Debug.METHOD_TAG, "onTrimMemory level is " + level);
	}
	
	private ServiceConnection mConnection = new ServiceConnection() {
		@Override
		public void onServiceDisconnected(ComponentName name) {
			mRemoteExecute = null;
			MyOldLog.p("remote execute disconnection");
		}

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			mRemoteExecute = IRemoteExecute.Stub.asInterface(service);

			MyOldLog.p("bindservice success");
			for (ConnectedRemoteExecute listener : mConnectedFinishListeners) {
				listener.onConnectedFinish(mRemoteExecute);
			}
		}
	};


    public interface OnInputModeChangeListener {
		void onInputModeChange(boolean isInTouchMode);
	}

	public interface OnRightFragmentPreDrawListener {
		void onRightFragmentPreDraw();
	}

	public interface OnHeaderListFocusChangeListener {
		void onHeaderListFocusChange(boolean hasFocus);
	}

	public interface OnKeyBackClickListener {
		boolean onKeyBack();
	}

	public interface OnInputMethodShowOrHideListener {
		void onInputMethodChange(boolean show);
	}

	public interface OnTouchBoardTouchedListener {
		/**
		 * the value contain
		 * 
		 * @param event
		 */
		void onTouchBoardTouched(KeyEvent event);
	};

	public interface OnMotionEventListener {
		void onMotion(MotionEvent e);
	}

    public interface OnTouchEventListener {
        void onTouchEvent(MotionEvent e);
    }

	public interface ConnectedRemoteExecute {
		void onConnectedFinish(IRemoteExecute remoteExecute);
	}

	// cmd

	// /adb shell top -m 3 -s rss
	// values-en
	// values-zh-rCN
	// values-zh-rTW
}
